package com.ssyx.service.impl;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssyx.constant.GlobalConstant;
import com.ssyx.enums.CouponRangeType;
import com.ssyx.enums.CouponStatus;
import com.ssyx.enums.CouponType;
import com.ssyx.mapper.CouponInfoMapper;
import com.ssyx.mapper.CouponRangeMapper;
import com.ssyx.mapper.CouponUseMapper;
import com.ssyx.model.activity.CouponInfo;
import com.ssyx.model.activity.CouponRange;
import com.ssyx.model.activity.CouponUse;
import com.ssyx.model.base.BaseEntity;
import com.ssyx.model.order.CartInfo;
import com.ssyx.model.product.Category;
import com.ssyx.model.product.SkuInfo;
import com.ssyx.product.ProductFeignClient;
import com.ssyx.service.CouponInfoService;
import com.ssyx.vo.activity.CouponRuleVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: ssyx-parent
 * @className: CouponInfoServiceImpl
 * @description: 类
 * @data: 2024/3/15 20:33
 * @author: ihu
 * @version: 1.0
 **/

@Slf4j
@Service
public class CouponInfoServiceImpl extends ServiceImpl<CouponInfoMapper, CouponInfo>
		implements CouponInfoService {
	
	@Resource
	private CouponInfoMapper couponInfoMapper;
	@Resource
	private CouponRangeMapper couponRangeMapper;
	@Resource
	private CouponUseMapper couponUseMapper;
	@Resource
	private ProductFeignClient productFeignClient;
	
	// 优惠卷分页查询
	@Override
	public IPage<CouponInfo> selectPage(Page<CouponInfo> pageParam) {
		// 构造排序
		IPage<CouponInfo> page = couponInfoMapper.selectPage(pageParam,
				Wrappers.<CouponInfo>lambdaQuery().orderByDesc(CouponInfo::getId));
		page.getRecords().forEach(this::setCouponInfo);
		// 返回数据集合
		return page;
	}
	
	// 根据id获取优惠券
	@Override
	public CouponInfo getCouponInfo(String id) {
		return setCouponInfo(getById(id));
	}
	
	//根据优惠卷id获取优惠券规则列表
	@Override
	public Map<String, Object> findCouponRuleList(Long couponId) {
		Map<String, Object> result = new HashMap<>();
		CouponInfo couponInfo = getById(couponId);
		// 优惠券规则列表
		List<CouponRange> activitySkuList =
				couponRangeMapper.selectList(Wrappers.<CouponRange>lambdaQuery().eq(CouponRange::getCouponId,
						couponId));
		List<Long> rangeIdList = activitySkuList.stream().map(CouponRange::getRangeId).collect(Collectors.toList());
		if (!CollectionUtils.isEmpty(rangeIdList)) {
			if (couponInfo.getRangeType().equals(CouponRangeType.SKU.getCode())) {
				List<SkuInfo> skuInfoList = productFeignClient.findSkuInfoList(rangeIdList);
				result.put("skuInfoList", skuInfoList);
			}
			if (couponInfo.getRangeType().equals(CouponRangeType.CATEGORY.getCode())) {
				List<Category> categoryList = productFeignClient.findCategoryList(rangeIdList);
				result.put("categoryList", categoryList);
			}
		}
		return result;
	}
	
	// 新增优惠券规则
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveCouponRule(CouponRuleVo couponRuleVo) {
		// 优惠券couponInfo 与 couponRange 要一起操作：先删除couponRange ，更新couponInfo ，再新增couponRange
		couponRangeMapper.delete(Wrappers.<CouponRange>lambdaQuery().eq(CouponRange::getCouponId,
				couponRuleVo.getCouponId()));
		// 更新数据
		CouponInfo couponInfo = getById(couponRuleVo.getCouponId());
		// couponInfo.setCouponType();
		couponInfo.setRangeType(couponRuleVo.getRangeType());
		couponInfo.setConditionAmount(couponRuleVo.getConditionAmount());
		couponInfo.setAmount(couponRuleVo.getAmount());
		couponInfo.setConditionAmount(couponRuleVo.getConditionAmount());
		couponInfo.setRangeDesc(couponRuleVo.getRangeDesc());
		updateById(couponInfo);
		// 插入优惠券的规则 couponRangeList
		couponRuleVo.getCouponRangeList().forEach(e -> {
			e.setCouponId(couponRuleVo.getCouponId());
			couponRangeMapper.insert(e);
		});
	}
	
	@Override
	public CouponInfo findRangeSkuIdList(List<CartInfo> cartInfoList, Long couponId) {
		//根据优惠卷id基本信息查询
		CouponInfo couponInfo = getById(couponId);
		if (couponInfo == null) {
			return null;
		}
		// 根据couponId查询对应CouponRange数据
		List<CouponRange> couponRangeList =
				couponRangeMapper.selectList(new LambdaQueryWrapper<CouponRange>().eq(CouponRange::getCouponId, couponId));
		//对应sku信息
		Map<Long, List<Long>> couponIdToSkuIdMap = findCouponIdToSkuIdMap(cartInfoList, couponRangeList);
		//遍历map，得到value值，封装到couponInfo对象
		couponInfo.setSkuIdList(couponIdToSkuIdMap.entrySet().iterator().next().getValue());
		return couponInfo;
	}
	
	@Override
	public void updateCouponInfoUseStatus(Long couponId, Long userId, Long orderId) {
		//根据couponId查询优惠卷信息
		CouponUse couponUse = couponUseMapper.selectOne(new LambdaQueryWrapper<CouponUse>().eq(CouponUse::getCouponId,
				couponId).eq(CouponUse::getUserId, userId).eq(CouponUse::getOrderId, orderId));
		//设置修改值
		couponUse.setCouponStatus(CouponStatus.USED.getCode());
		//调用方法修改
		couponUseMapper.updateById(couponUse);
	}
	
	@Override
	public List<CouponInfo> findCartCouponInfo(List<CartInfo> cartInfoList, Long userId) {
		List<CouponInfo> userAllCouponInfoList = couponInfoMapper.selectCartCouponInfoList(userId);
		if (CollectionUtils.isEmpty(userAllCouponInfoList)) {
			return new ArrayList<>();
		}
		// 获取所有优惠卷id列表
		List<Long> couponIdList = userAllCouponInfoList.stream().map(BaseEntity::getId).collect(Collectors.toList());
		// 查询优惠卷对应的范围
		List<CouponRange> couponRangeList =
				couponRangeMapper.selectList(Wrappers.<CouponRange>lambdaQuery().in(CouponRange::getCouponId, couponIdList));
		
		// 获取优惠卷id 对应skuId列表 优惠卷id进行分组，得到map集合
		Map<Long, List<Long>> couponIdToSkuIdMap = findCouponIdToSkuIdMap(cartInfoList, couponRangeList);
		// 遍历全部优惠卷集合，判断优惠卷类型
		BigDecimal reduceAmount = new BigDecimal(GlobalConstant.INTEGER_ZERO);
		CouponInfo optimalCouponInfo = null;
		for (CouponInfo couponInfo : userAllCouponInfoList) {
			//全场通用
			if (CouponRangeType.ALL.getCode().equals(couponInfo.getRangeType())) {
				//全场通用
				//判断是否满足优惠使用门槛
				//计算购物车商品的总价
				BigDecimal totalAmount = computeTotalAmount(cartInfoList);
				if (totalAmount.subtract(couponInfo.getConditionAmount()).doubleValue() >= GlobalConstant.INTEGER_ZERO) {
					couponInfo.setIsSelect(GlobalConstant.INTEGER_ONE);
				}
			} else {
				//优惠卷id获取对应skuId列表
				List<Long> skuIdList
						= couponIdToSkuIdMap.get(couponInfo.getId());
				//满足使用范围购物项
				List<CartInfo> currentCartInfoList = cartInfoList.stream()
						.filter(cartInfo -> skuIdList.contains(cartInfo.getSkuId()))
						.collect(Collectors.toList());
				BigDecimal totalAmount = computeTotalAmount(currentCartInfoList);
				if (totalAmount.subtract(couponInfo.getConditionAmount()).doubleValue() >= GlobalConstant.INTEGER_ZERO) {
					couponInfo.setIsSelect(GlobalConstant.INTEGER_ONE);
				}
			}
			if (couponInfo.getIsSelect().intValue() == GlobalConstant.INTEGER_ONE && couponInfo.getAmount().subtract(reduceAmount).doubleValue() > GlobalConstant.INTEGER_ZERO) {
				reduceAmount = couponInfo.getAmount();
				optimalCouponInfo = couponInfo;
			}
			
		}
		//6 返回List<CouponInfo>
		if (null != optimalCouponInfo) {
			optimalCouponInfo.setIsOptimal(GlobalConstant.INTEGER_ONE);
		}
		return userAllCouponInfoList;
	}
	
	@Override
	public List<CouponInfo> findCouponInfoList(Long skuId, Long userId) {
		//远程调用：根据skuId获取skuInfo
		SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
		//根据条件查询：skuId + 分类id + userId
		return baseMapper.selectCouponInfoList(skuInfo.getId(),
				skuInfo.getCategoryId(), userId);
	}
	
	private BigDecimal computeTotalAmount(List<CartInfo> cartInfoList) {
		BigDecimal total = new BigDecimal(GlobalConstant.INTEGER_ZERO);
		for (CartInfo cartInfo : cartInfoList) {
			//是否选中
			if (cartInfo.getIsChecked().intValue() == GlobalConstant.INTEGER_ONE) {
				BigDecimal itemTotal = cartInfo.getCartPrice().multiply(new BigDecimal(cartInfo.getSkuNum()));
				total = total.add(itemTotal);
			}
		}
		return total;
	}
	
	//优惠卷id进行分组，得到map集合
	private Map<Long, List<Long>> findCouponIdToSkuIdMap(List<CartInfo> cartInfoList,
	                                                     List<CouponRange> couponRangeList) {
		Map<Long, List<Long>> couponIdToSkuIdMap = new HashMap<>();
		
		//couponRangeList数据处理，根据优惠卷id分组
		Map<Long, List<CouponRange>> couponRangeToRangeListMap =
				couponRangeList.stream().collect(Collectors.groupingBy(CouponRange::getCouponId));
		//遍历map集合
		for (Map.Entry<Long, List<CouponRange>> entry : couponRangeToRangeListMap.entrySet()) {
			Long couponId = entry.getKey();
			List<CouponRange> rangeList = entry.getValue();
			//创建集合 set
			Set<Long> skuIdSet = new HashSet<>();
			for (CartInfo cartInfo : cartInfoList) {
				for (CouponRange couponRange : rangeList) {
					//判断
					if (couponRange.getRangeType().equals(CouponRangeType.SKU.getCode())
							&& couponRange.getRangeId().longValue() == cartInfo.getSkuId().longValue()) {
						skuIdSet.add(cartInfo.getSkuId());
					} else if (couponRange.getRangeType().equals(CouponRangeType.CATEGORY.getCode())
							&& couponRange.getRangeId().longValue() == cartInfo.getCategoryId().longValue()) {
						skuIdSet.add(cartInfo.getSkuId());
					}
				}
			}
			couponIdToSkuIdMap.put(couponId, new ArrayList<>(skuIdSet));
		}
		return couponIdToSkuIdMap;
	}
	
	private CouponInfo setCouponInfo(CouponInfo couponInfo) {
		if (couponInfo.getCouponType().equals(CouponType.FULL_REDUCTION.getCode())) {
			couponInfo.setCouponTypeString(CouponType.FULL_REDUCTION.getComment());
		} else {
			couponInfo.setCouponTypeString(CouponType.CASH.getComment());
		}
		if (couponInfo.getRangeType() != null) {
			if (couponInfo.getRangeType().equals(CouponRangeType.ALL.getCode())) {
				couponInfo.setRangeTypeString(CouponRangeType.ALL.getComment());
			} else if (couponInfo.getRangeType().equals(CouponRangeType.SKU.getCode())) {
				couponInfo.setRangeTypeString(CouponRangeType.SKU.getComment());
			} else if (couponInfo.getRangeType().equals(CouponRangeType.CATEGORY.getCode())) {
				couponInfo.setRangeTypeString(CouponRangeType.CATEGORY.getComment());
			}
		}
		return couponInfo;
	}
}
